package model.dtos;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import model.beans.Pair;
import model.beans.RandomNumbers;
import model.daos.GameDao;

public class Season
{
	
	List<Team> teams;
	List<Umpire> umpires;
	List<Game> games;
	boolean[][] gamesPlayed;

	public Season()
	{
		teams = new ArrayList<Team>();
		umpires = new ArrayList<Umpire>();
		games = new ArrayList<Game>();
	}
	
	public List<Team> getTeams()
	{
		return teams;
	}

	public void setTeams(List<Team> teams)
	{
		this.teams = teams;
	}

	public List<Umpire> getUmpires()
	{
		return umpires;
	}

	public void setUmpires(List<Umpire> umpires)
	{
		this.umpires = umpires;
	}

	public List<Game> getGames()
	{
		return games;
	}

	public void setGames(List<Game> games)
	{
		this.games = games;
	}
	
	public void addGame (Game g)
	{
		this.games.add(g);
	}

	public void addUmpire (Umpire u)
	{
		this.umpires.add(u);
	}
	
	public void addTeam (Team t)
	{
		this.teams.add(t);
	}
	
	private List<Pair<Integer, Integer>> generateGamePairs(int N)
	{
		List<Pair<Integer, Integer>> pairs = new ArrayList<Pair<Integer, Integer>>();
		
		for (int t = 0; t < 2; ++t)
			for (int i = 0; i < N - 1; ++i)
				for (int j = 1 + i; j < N; ++j)
						pairs.add(new Pair<Integer, Integer>(i, j));
		
		for (int t = 0; t < 2; ++t)
			for (int i = 0; i < N - 1; ++i)
				for (int j = 1 + i; j < N; ++j)
					pairs.add(new Pair<Integer, Integer>(j, i));
		
		return pairs;
	}
	
	private void simulateGame (int team1, int team2, Date date, String code)
	{
		int inningsPlayed = 9;
		Player pHrTeam1 = null;
		Player pHrTeam2 = null;
		Player pRbisTeam1 = null;
		Player pRbisTeam2 = null;
		boolean extraInning = false;
		int hrs = RandomNumbers.random(0, 2);
		int teamHr = RandomNumbers.random(0, 1);
		
		int scoreTeam1 = RandomNumbers.random(teamHr == 0 ? hrs : 0, 15);
		int scoreTeam2 = RandomNumbers.random(teamHr == 1 ? hrs : 0, 15);
		
		while (scoreTeam1 == scoreTeam2)
		{
			scoreTeam1 = RandomNumbers.random(teamHr == 0 ? hrs : 0, 15);
			scoreTeam2 = RandomNumbers.random(teamHr == 1 ? hrs : 0, 15);
			extraInning = true;
			++inningsPlayed;
		}
		
		if (teamHr == 0)
		{
			int K = RandomNumbers.random(0, teams.get(team1).getPlayers().size() - 1);
			pHrTeam1 = teams.get(team1).getPlayers().get(K);
			teams.get(team1).getPlayers().get(K).addHrs(hrs);
		}
		
		if (teamHr == 1)
		{
			int K = RandomNumbers.random(0, teams.get(team2).getPlayers().size() - 1);
			pHrTeam2 = teams.get(team2).getPlayers().get(K);
			teams.get(team2).getPlayers().get(K).addHrs(hrs);
		}
		
		if (scoreTeam1 > 0)
		{
			int K = RandomNumbers.random(0, teams.get(team1).getPlayers().size() - 1);
			pRbisTeam1 = teams.get(team1).getPlayers().get(K);
			teams.get(team1).getPlayers().get(K).addRbis(scoreTeam1 - (teamHr == 0 ? hrs : 0));
		}
		
		if (scoreTeam2 > 0)
		{
			int K = RandomNumbers.random(0, teams.get(team2).getPlayers().size() - 1);
			pRbisTeam2 = teams.get(team2).getPlayers().get(K);
			teams.get(team2).getPlayers().get(K).addRbis(scoreTeam2 - (teamHr == 1 ? hrs : 0));
		}
		
		if (scoreTeam1 > scoreTeam2)
		{
			teams.get(team1).addWonGame();
			teams.get(team2).addLostGame();
		}
		else
		{
			teams.get(team2).addWonGame();
			teams.get(team1).addLostGame();
		}
		
		boolean validUmpire = false;
		int umpireNum = 0;
		
		while (!validUmpire)
		{
			umpireNum = RandomNumbers.random(0, umpires.size() - 1);
			
			if (!date.equals(umpires.get(umpireNum).getLastArbitrated()))
			{
				umpires.get(umpireNum).setLastArbitrated(date);
				umpires.get(umpireNum).addArbitratedGame(1);
				validUmpire = true;
			}
			
		}
		
		GameDao gameDao = new GameDao();
		gameDao.save(new Game(code, date, teams.get(team1), teams.get(team2), umpires.get(umpireNum), pRbisTeam1, pRbisTeam2, pHrTeam1, pHrTeam2 ,inningsPlayed, scoreTeam1, scoreTeam2, hrs, extraInning));
	}
	
	public void playSeason()
	{	
		
		games.clear();
		
		List<Pair<Integer, Integer>> pairs = generateGamePairs(teams.size());
		List<Pair<Pair<Integer, Integer>, Boolean>> games = new ArrayList<Pair<Pair<Integer, Integer>, Boolean>>();
		int code = 0;
		
		for (int i = 0; i < pairs.size(); ++i)
			games.add(new Pair<Pair<Integer, Integer>, Boolean>(pairs.get(i), false));
			
		Calendar calendar = Calendar.getInstance();		
			
		for (int i = 0; i < (teams.size() - 1) * 4; ++i)
		{				
			if (calendar.get(Calendar.DAY_OF_WEEK) == 2)
				calendar.add(Calendar.DATE, 1);
					
			boolean[] gm = new boolean[teams.size()];
			for (int t = 0; t < teams.size(); ++t) gm[t] = false;
					
					
			for (int j = 0; j < games.size(); ++j)
			{
				if (!gm[games.get(j).getLeft().getLeft()] && !gm[games.get(j).getLeft().getRight()] && games.get(j).getRight() == false)
				{
					simulateGame(games.get(j).getLeft().getLeft(), games.get(j).getLeft().getRight(), ((Calendar)calendar.clone()).getTime(), String.valueOf(++code));
						
					games.get(j).setRight(true);
					gm[games.get(j).getLeft().getLeft()] = true;
					gm[games.get(j).getLeft().getRight()] = true;
				}
			}
			calendar.add(Calendar.DATE, 1);
		}
		
		for (int i = 0; i < games.size(); ++i)
		{
			if (!games.get(i).getRight())
			{
				simulateGame(games.get(i).getLeft().getLeft(), games.get(i).getLeft().getRight(), ((Calendar)calendar.clone()).getTime(), String.valueOf(++code));
			
				calendar.add(Calendar.DATE, 1);
				
				if (calendar.get(Calendar.DAY_OF_WEEK) == 2)
					calendar.add(Calendar.DATE, 1);
				
			}
		}
	}
}
